package com.baichuan.netty;

import lombok.Data;

import java.io.Serializable;

@Data
public class GeoUtils implements Serializable {
    // 地球半径，单位：米
    private static final double EARTH_RADIUS = 6371000;

    // 将角度转换为弧度
    public static double toRadians(double degree) {
        return degree * Math.PI / 180.0;
    }

    // 计算两个经纬度点之间的距离，单位：米
    public static double haversine(double lat1, double lon1, double lat2, double lon2) {
        double lat1Rad = toRadians(lat1);
        double lon1Rad = toRadians(lon1);
        double lat2Rad = toRadians(lat2);
        double lon2Rad = toRadians(lon2);

        double dLat = lat2Rad - lat1Rad;
        double dLon = lon2Rad - lon1Rad;

        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
                + Math.cos(lat1Rad) * Math.cos(lat2Rad)
                * Math.sin(dLon / 2) * Math.sin(dLon / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        // 返回两个点之间的距离，单位：米
        return EARTH_RADIUS * c;
    }

    // 计算点到直线的最短距离，单位：米
    public static double pointToLineDistance(double lat1, double lon1, double lat2, double lon2, double latCheck, double lonCheck) {
        // 计算线段的距离
        double lineLength = haversine(lat1, lon1, lat2, lon2);

        // 计算待判断点到两点的距离
        double distanceToStart = haversine(latCheck, lonCheck, lat1, lon1);
        double distanceToEnd = haversine(latCheck, lonCheck, lat2, lon2);

        // 判断待判断点是否在线段的延长线上
        if (distanceToStart + distanceToEnd == lineLength) {
            return Math.min(distanceToStart, distanceToEnd);
        } else {
            // 如果点不在线段上，计算点到直线的最短距离
            double area = Math.abs(lat1 * (lon2 - lonCheck) + lat2 * (lonCheck - lon1) + latCheck * (lon1 - lon2));
            double lineDistance = area / lineLength;
            return lineDistance;
        }
    }

    // 判断待判断点是否在50米范围内
    public static boolean isPointNearLine(double lat1, double lon1, double lat2, double lon2, double latCheck, double lonCheck, double radius) {
        double distance = pointToLineDistance(lat1, lon1, lat2, lon2, latCheck, lonCheck);
        return distance <= radius;
    }

    public static void main(String[] args) {
        for (int i = 0; i <100000 ; i++) {
            // 点1 (纬度, 经度)
            double lat1 = 40.712776, lon1 = -74.005974;
            // 点2
            double lat2 = 40.713776, lon2 = -74.004974;
            // 待判断点
            double latCheck = 40.712900, lonCheck = -74.005200;

            // 半径50米
            double radius = 50.0;
            isPointNearLine(lat1, lon1, lat2, lon2, latCheck, lonCheck, radius);
            // 判断点是否在50米范围内
//            if (isPointNearLine(lat1, lon1, lat2, lon2, latCheck, lonCheck, radius)) {
//                System.out.println("该点在50米范围内");
//            } else {
//                System.out.println("该点不在50米范围内");
//            }
        }
    }
}
